package org.dicr.util.jds;

import java.io.*;
import java.sql.*;

import org.dicr.util.data.exc.*;

import com.borland.datastore.*;
import com.borland.dx.dataset.*;
import com.borland.dx.sql.dataset.*;

/***********************************************************************************************************************
 * @author Igor A Tarasov me@dicr.dn.ua
 * @version 031106
 **********************************************************************************************************************/
public class DataStoreUtils {
	/*******************************************************************************************************************
	 * Возвращает SQL тип по типу колонки Variant
	 * 
	 * @param variantType column type
	 * @return sql type
	 ******************************************************************************************************************/
	public static String getSQLType(int variantType) {
		switch (variantType) {
			case Variant.BIGDECIMAL:
				return "DECIMAL";
			case Variant.BOOLEAN:
				return "BOOLEAN";
			case Variant.BYTE:
				return "SHORT";
			case Variant.BYTE_ARRAY:
				return "VARBINARY";
			case Variant.DATE:
				return "DATE";
			case Variant.DOUBLE:
				return "DOUBLE";
			case Variant.FLOAT:
				return "REAL";
			case Variant.INPUTSTREAM:
				return "INPUTSTREAM";
			case Variant.INT:
				return "INTEGER";
			case Variant.LONG:
				return "LONG";
			case Variant.OBJECT:
				return "VARBINARY";
			case Variant.SHORT:
				return "SHORT";
			case Variant.STRING:
				return "STRING";
			case Variant.TIME:
				return "TIME";
			case Variant.TIMESTAMP:
				return "TIMESTAMP";
			default:
				throw new IllegalArgumentException(
				        "Неверное значение аргумента variantType или variantType имеет тип NULL");
		}
	}

	/*******************************************************************************************************************
	 * При необходимости (зависит от типа) заключает значение в кавычки
	 * 
	 * @param variantType column type
	 * @param value value to quote
	 * @return quotes value
	 ******************************************************************************************************************/
	public static String quoteValue(int variantType, String value) {
		if (value == null) return "NULL";
		switch (variantType) {
			case Variant.DATE:
				return (value.equals("now") || value.equals("today")) ? "'" + value + "'" : "DATE'" + value + "'";
			case Variant.STRING:
				return "'" + value + "'";
			case Variant.TIME:
				return (value.equals("now") || value.equals("today")) ? "'" + value + "'" : "TIME'" + value + "'";
			case Variant.TIMESTAMP:
				return (value.equals("now") || value.equals("today")) ? "'" + value + "'" : "TIMESTAMP'" + value + "'";
			case Variant.NULL_TYPES:
				return "NULL";
		}
		return value;
	}

	/*******************************************************************************************************************
	 * Возвращает CREATE TABLE запрос согласно заданному DataSet
	 * 
	 * @param dataset dataset to generate sql
	 * @return generated sql
	 ******************************************************************************************************************/
	public static String getCreateSQL(QueryDataSet dataset) {
		Column[] columns = dataset.getColumns();
		if (columns == null || columns.length <= 0) throw new IllegalStateException("Нет колонок у DataSet");
		String tablename = dataset.getTableName();
		if (tablename == null || tablename.length() < 1) throw new IllegalStateException(
		        "Не задано tableName у QueryDataSet");
		StringBuffer buf = new StringBuffer("CREATE TABLE \"" + tablename + "\"(");
		for (int i = 0; i < columns.length; i++) {
			Column col = columns[i];
			if (!col.isResolvable()) {
				continue;
			}
			buf.append('"' + col.getServerColumnName() + "\" " + DataStoreUtils.getSQLType(col.getDataType()));
			if (col.getPrecision() >= 0 || col.getScale() >= 0) {
				int precis = (col.getPrecision() >= 0) ? col.getPrecision() : 10;
				int scale = (col.getScale() >= 0) ? col.getScale() : 0;
				buf.append("(" + precis + "," + scale + ")");
			}
			if (col.getDefault() != null) {
				buf.append(" DEFAULT " + DataStoreUtils.quoteValue(col.getDataType(), col.getDefault()));
			}
			if (col.isRequired()) {
				buf.append(" NOT NULL");
			}
			if (col.isAutoIncrement()) {
				buf.append(" AUTOINCREMENT");
			}
			if (col.isRowId()) {
				buf.append(" PRIMARY KEY");
			}
			buf.append(", ");
		}
		buf.delete(buf.length() - 2, buf.length() - 1);
		buf.append(")");
		return buf.toString();
	}

	/*******************************************************************************************************************
	 * Создает таблицы в базе данных
	 * 
	 * @param dss dataset
	 * @throws DataException error
	 ******************************************************************************************************************/
	public static void createTables(QueryDataSet[] dss) throws DataException {
		try {
			for (int i = 0; i < dss.length; i++) {
				Statement st = dss[i].getDatabase().createStatement();
				st.executeUpdate(getCreateSQL(dss[i]));
				st.close();
			}
		} catch (Exception ex) {
			throw new DataException("Ошибка создания таблиц", ex);
		}
	}

	/*******************************************************************************************************************
	 * Создает локальную базу данных
	 * 
	 * @param filename file of database
	 * @return datastore
	 * @throws DataException
	 ******************************************************************************************************************/
	public static DataStore createDatabase(String filename) throws DataException {
		if (filename == null) throw new IllegalArgumentException("NULL filename");
		DataStore ds = null;
		File file = new File(filename);
		try {
			if (file.exists()) throw new IOException("Файл: " + file.getName() + " уже существует");
			file = new File(checkDataFileName(file.getAbsolutePath()));
			File dir = file.getParentFile();
			if (!dir.exists()) dir.mkdirs();
			ds = new DataStore();
			ds.setFileName(file.getAbsolutePath());
			ds.setAutoShutdown(true);
			ds.setTxManager(new TxManager());
			ds.setUserName("SYSDBA");
			ds.create();
			ds.addUser("masterkey", "akusher", "akpas", DataStoreRights.FULL_RIGHTS);
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new DataException("Ошибка создания базы данных " + file.getName(), ex);
		}
		return ds;
	}

	/*******************************************************************************************************************
	 * Добавляет при необходимости расширение файла .jds
	 * 
	 * @param filename filename to check
	 * @return modified file name
	 ******************************************************************************************************************/
	public static String checkDataFileName(String filename) {
		if (filename == null) throw new IllegalArgumentException("NULL filename");
		return filename.toLowerCase().endsWith(".jds") ? filename : filename + ".jds";
	}
}
